# -*- coding: utf-8 -*-
# flake8: noqa

import configparser
import logging
import shutil
import time
import os

from PIL import Image
from shutil import copyfile


def get_size(file):
    """
    获取文件大小
    :param file:文件路径
    :return:
    """
    # 获取文件大小:KB
    size = os.path.getsize(file)
    return int(size / 1024)


def compress_image(infile, outfile='', mb=3000, step=5, quality=80):
    """不改变图片尺寸压缩到指定大小
    :param infile: 压缩源文件
    :param outfile: 压缩文件保存地址
    :param mb: 压缩目标，KB
    :param step: 每次调整的压缩比率
    :param quality: 初始压缩比率
    :return: 压缩文件地址，压缩文件大小
    """
    o_size = get_size(infile)
    if o_size <= mb:
        copyfile(infile, outfile)
        return infile
    copyfile(infile, outfile)
    while o_size > mb:
        im = Image.open(outfile)
        im = im.convert('RGB')
        im.save(outfile, quality=quality)
        if quality - step < 0:
            break
        quality -= step
        o_size = get_size(outfile)
    return outfile, get_size(outfile)


def getFileNameExtension(file_name):
    """
    获取文件名后缀
    :param file_name:完整文件名
    :return: (文件名, 后缀)
    """
    file_name_s = os.path.splitext(file_name)
    return file_name_s[0], file_name_s[1]


def compressPicture(in_folder_path, in_file_path, in_file_name, in_zip_max):
    """
    对图片进行压缩的逻辑
    :param in_folder_path: 输入的文件夹地址
    :param in_file_path: 被压缩图片地址
    :param in_file_name: 被压缩图片名称
    :param in_zip_max: 压缩到多少空间以下
    :return:
    """
    # 检测目录是否存在
    if os.path.exists(in_folder_path + "/temp") is False:
        # 不存在则创建目录
        os.mkdir(in_folder_path + "/temp")
    folder_name = in_folder_path.split("/")[-1]
    logging.info("当前文件:" + in_file_path)
    logging.info("文件压缩前大小:" + str(get_size(in_file_path)) + "KB")
    compress_image(in_file_path, outfile=in_folder_path + "/temp/" + in_file_name + '.jpg', mb=int(in_zip_max), step=10, quality=80)
    logging.info("压缩完成！")
    logging.info("文件压缩后大小:" + str(get_size(in_folder_path + "/temp/" + in_file_name + '.jpg')) + "KB\n")
    # 检测目录是否存在
    if os.path.exists(in_folder_path + "/" + folder_name) is False:
        # 不存在则创建目录
        os.mkdir(in_folder_path + "/" + folder_name)
    copyfile(in_folder_path + "/temp/" + in_file_name + '.jpg', in_folder_path + "/" + folder_name + "/" + in_file_name + '.jpg')
    os.remove(in_folder_path + "/temp/" + in_file_name + '.jpg')


if __name__ == '__main__':
    # 日志相关配置
    LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
    DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"
    logging.basicConfig(filename="log/system.log", level=logging.INFO, format=LOG_FORMAT, datefmt=DATE_FORMAT)
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    formatter = logging.Formatter(LOG_FORMAT)
    console.setFormatter(formatter)
    logging.getLogger('').addHandler(console)
    # config信息配置
    conf = configparser.ConfigParser()
    conf.read("config.ini", encoding="utf-8")
    # 获取基本信息
    zip_max = conf.get("info", "zip_max")
    file_extensions = conf.get("info", "file_extensions")
    file_extensions = file_extensions.split("/")

    print("╔═════════════════════════════════╗")
    print("║ PictureZipTool    by NC         ║")
    print("╚═════════════════════════════════╝")
    while True:
        folder_path = input("请输入需要压缩的文件夹地址:")
        folder_path = folder_path.replace("\\", "/")
        # 列出文件夹下所有的目录与文件
        path_list = os.listdir(folder_path)
        # 遍历列表
        for i in range(0, len(path_list)):
            # 拼接完整地址
            path = folder_path + "/" + path_list[i]
            # 判断该地址是文件的地址（判断是否是文件）
            if os.path.isfile(path):
                # 获取该文件的文件名以及后缀
                file_name, file_extension = getFileNameExtension(path_list[i])
                # 判断后缀是否是在需要处理的类型中
                if file_extension in file_extensions:
                    # 对图片进行压缩
                    try:
                        compressPicture(folder_path, path, file_name, zip_max)
                    except Exception as e:
                        logging.error("处理压缩时出现异常,准备重新对该文件压缩...")
                        error_count = 0
                        while True:
                            try:
                                logging.error("第" + str(error_count + 1) + "次尝试压缩...")
                                time.sleep(1)
                                if error_count >= 5:
                                    logging.error("处理压缩时出现异常:")
                                    logging.error("异常文件:" + path)
                                    input("按回车键跳过")
                                    break
                                compressPicture(folder_path, path, file_name, zip_max)
                                break
                            except Exception as sub_e:
                                error_count += 1

        # 全部完成清除临时文件夹
        shutil.rmtree(folder_path + "/temp")

